package com.lanvideo.controller;

import com.lanvideo.service.VideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 视频流媒体控制器
 */
@RestController
@RequestMapping("/api/video")
public class VideoStreamController {

    @Value("${video.upload-path:D:/lan-video/}")
    private String uploadPath;
    
    @Autowired
    private VideoService videoService;

    /**
     * 通过ID获取视频流
     */
    @GetMapping("/stream/{id}")
    public ResponseEntity<Resource> streamVideoById(@PathVariable String id, HttpServletRequest request) {
        try {
            System.out.println("=== VideoStreamController.streamVideoById Debug ===");
            System.out.println("Video ID/Path: " + id);
            
            // 检查用户权限
            Integer userRole = (Integer) request.getSession().getAttribute("userRole");
            Integer userId = (Integer) request.getSession().getAttribute("userId");
            boolean isAdmin = userRole != null && userRole == 0;
            boolean isTeacher = userRole != null && userRole == 1;
            boolean isStudent = userRole != null && userRole == 2;
            
            System.out.println("User Role: " + userRole);
            System.out.println("User ID: " + userId);
            System.out.println("Is Admin: " + isAdmin);
            System.out.println("Is Teacher: " + isTeacher);
            System.out.println("Is Student: " + isStudent);
            
            // 权限检查
            if (!isAdmin && !isTeacher && !isStudent) {
                System.out.println("User not logged in");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
            }
            
            // 构建文件路径
            Path uploadDir = Paths.get(uploadPath).toAbsolutePath().normalize();
            Path videoFile;
            
            // 判断id是数字ID还是文件名
            if (id.matches("\\d+")) {
                // 数字ID，从数据库获取视频信息
                Integer videoId = Integer.parseInt(id);
                com.lanvideo.entity.Video video = videoService.getVideoById(videoId);
                if (video == null) {
                    System.out.println("Video not found in database for ID: " + videoId);
                    return ResponseEntity.notFound().build();
                }
                
                System.out.println("Video found: " + video.getTitle());
                System.out.println("Video path: " + video.getPath());
                System.out.println("Video status: " + video.getStatus());
                System.out.println("Video uploader ID: " + video.getUploaderId());
                
                // 权限检查逻辑
                if (isAdmin) {
                    // 管理员可以访问所有视频
                } else if (isTeacher) {
                    // 老师可以访问自己发布的所有视频（包括未审核的）
                    if (userId != null && userId.equals(video.getUploaderId())) {
                    } else {
                        // 老师只能访问已审核通过的视频
                        if (video.getStatus() == null || video.getStatus() != 1) {
                            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
                        }
                    }
                } else if (isStudent) {
                    // 学生只能访问已审核通过的视频
                    if (video.getStatus() == null || video.getStatus() != 1) {
                        return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
                    }
                }
                
                videoFile = uploadDir.resolve(video.getPath()).normalize();
            } else {
                // 文件名，直接访问（仅管理员可用）
                if (!isAdmin) {
                    System.out.println("Direct file access only allowed for admin");
                    return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
                }
                videoFile = uploadDir.resolve(id).normalize();
            }
            
            System.out.println("Upload path: " + uploadPath);
            System.out.println("Upload dir: " + uploadDir);
            System.out.println("Video file path: " + videoFile);
            
            // 安全检查
            if (!videoFile.startsWith(uploadDir)) {
                System.out.println("Security check failed: file path outside upload directory");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
            }
            
            File file = videoFile.toFile();
            System.out.println("File exists: " + file.exists());
            System.out.println("File is file: " + file.isFile());
            System.out.println("File size: " + (file.exists() ? file.length() : "N/A"));
            
            if (!file.exists()) {
                System.out.println("File not found: " + videoFile);
                return ResponseEntity.notFound().build();
            }
            if (!file.isFile()) {
                System.out.println("Path is not a file: " + videoFile);
                return ResponseEntity.notFound().build();
            }
            
            Resource resource = new FileSystemResource(file);
            
            // 确定媒体类型 - 改进的检测逻辑
            String contentType = getContentType(file);
            System.out.println("Detected Content-Type: " + contentType);
            
            // 支持范围请求
            String range = request.getHeader("Range");
            if (range != null) {
                return handleRangeRequest(resource, range, contentType, file);
            }
            
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type", contentType);
            headers.add("Content-Length", String.valueOf(file.length()));
            headers.add("Accept-Ranges", "bytes");
            headers.add("Cache-Control", "public, max-age=3600");
            headers.add("X-Content-Type-Options", "nosniff");
            headers.add("Access-Control-Allow-Origin", "*");
            headers.add("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
            headers.add("Access-Control-Allow-Headers", "Range, Content-Type, Accept");
            
            System.out.println("Successfully serving video file: " + videoFile);
            System.out.println("Content-Type: " + contentType);
            System.out.println("Content-Length: " + file.length());
            System.out.println("=== End VideoStreamController Debug ===");
            
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);
                    
        } catch (Exception e) {
            System.out.println("Exception in streamVideoById: " + e.getMessage());
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    /**
     * 视频流媒体播放（通过路径）
     */
    @GetMapping("/stream")
    public ResponseEntity<Resource> streamVideo(@RequestParam String path, HttpServletRequest request) {
        try {
            // 安全检查：确保路径在允许的目录内
            Path videoPath = Paths.get(path);
            Path uploadDir = Paths.get(uploadPath).toAbsolutePath().normalize();
            Path resolvedPath = uploadDir.resolve(videoPath.getFileName()).normalize();
            
            if (!resolvedPath.startsWith(uploadDir)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
            }
            
            File videoFile = resolvedPath.toFile();
            if (!videoFile.exists() || !videoFile.isFile()) {
                return ResponseEntity.notFound().build();
            }
            
            Resource resource = new FileSystemResource(videoFile);
            
            // 确定媒体类型
            String contentType = Files.probeContentType(videoFile.toPath());
            if (contentType == null) {
                contentType = "video/mp4"; // 默认类型
            }
            
            // 支持范围请求（用于视频播放的拖拽进度条）
            String range = request.getHeader("Range");
            if (range != null) {
                return handleRangeRequest(resource, range, contentType, videoFile);
            }
            
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .contentLength(videoFile.length())
                    .body(resource);
                    
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
    
    /**
     * 获取文件的Content-Type
     */
    private String getContentType(File file) {
        try {
            // 首先尝试使用Files.probeContentType
            String contentType = Files.probeContentType(file.toPath());
            if (contentType != null && contentType.startsWith("video/")) {
                return contentType;
            }
        } catch (IOException e) {
            System.out.println("Failed to probe content type: " + e.getMessage());
        }
        
        // 根据文件扩展名确定类型
        String fileName = file.getName().toLowerCase();
        if (fileName.endsWith(".mp4")) {
            return "video/mp4";
        } else if (fileName.endsWith(".avi")) {
            return "video/x-msvideo";
        } else if (fileName.endsWith(".mov")) {
            return "video/quicktime";
        } else if (fileName.endsWith(".wmv")) {
            return "video/x-ms-wmv";
        } else if (fileName.endsWith(".flv")) {
            return "video/x-flv";
        } else if (fileName.endsWith(".webm")) {
            return "video/webm";
        } else if (fileName.endsWith(".mkv")) {
            return "video/x-matroska";
        } else if (fileName.endsWith(".m4v")) {
            return "video/x-m4v";
        } else if (fileName.endsWith(".3gp")) {
            return "video/3gpp";
        } else {
            return "video/mp4"; // 默认类型
        }
    }
    
    /**
     * 处理范围请求（支持视频拖拽）
     */
    private ResponseEntity<Resource> handleRangeRequest(Resource resource, String range, String contentType, File file) {
        try {
            long fileLength = file.length();
            if (fileLength <= 0) {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
            
            long start = 0;
            long end = fileLength - 1;
            
            // 解析Range头
            if (range.startsWith("bytes=")) {
                String rangeValue = range.substring(6);
                String[] ranges = rangeValue.split("-");
                
                if (ranges.length >= 1 && !ranges[0].isEmpty()) {
                    start = Long.parseLong(ranges[0]);
                }
                
                if (ranges.length > 1 && !ranges[1].isEmpty()) {
                    end = Long.parseLong(ranges[1]);
                }
                
                // 确保范围有效
                if (start < 0) start = 0;
                if (end >= fileLength) end = fileLength - 1;
                if (start > end) {
                    return ResponseEntity.status(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE).build();
                }
            }
            
            long contentLength = end - start + 1;
            
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type", contentType);
            headers.add("Content-Length", String.valueOf(contentLength));
            headers.add("Accept-Ranges", "bytes");
            headers.add("Content-Range", "bytes " + start + "-" + end + "/" + fileLength);
            headers.add("Cache-Control", "public, max-age=3600");
            headers.add("X-Content-Type-Options", "nosniff");
            headers.add("Access-Control-Allow-Origin", "*");
            headers.add("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
            headers.add("Access-Control-Allow-Headers", "Range, Content-Type, Accept");
            
            System.out.println("Range request: " + range + " -> " + start + "-" + end + "/" + fileLength);
            
            return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
                    .headers(headers)
                    .body(resource);
                    
        } catch (NumberFormatException e) {
            System.out.println("Invalid range format: " + range);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        } catch (Exception e) {
            System.out.println("Error handling range request: " + e.getMessage());
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
}
